#include<stdio.h>
#include<stdlib.h> // free
#include<sys/ioctl.h>
#include<unistd.h>
#include<termios.h>

#include"processBar.h"


void pBar_step_newLine(pBar_t *ctx, __uint16_t barII);
void pBar_step(pBar_t *ctx, __uint16_t barII);
void pBar_release(pBar_t *ctx);

const processBar_backend_t _processBar_backend = {
    pBar_step_newLine,
    pBar_step,
    pBar_release
};

pBar_t* pBar_init(__uint16_t barN)
{
    __uint16_t blockN=100;
    pBar_t* ctx;
    struct winsize winS;

    ctx = (pBar_t *)malloc(sizeof(pBar_t));
    if (ctx == NULL) {
        return NULL;
    }
    ioctl(STDIN_FILENO,TIOCGWINSZ,&winS);
    ctx->blockN=(winS.ws_col<blockN?winS.ws_col:blockN)-7;
    ctx->barN=barN;
    ctx->backend=(processBar_backend_t*)malloc(sizeof(processBar_backend_t));
    if(ctx->backend==NULL)
    {
        free(ctx);
        return NULL;
    }
    ctx->backend=&_processBar_backend;
    return ctx;
}

void pBar_step_newLine(pBar_t *ctx, __uint16_t barII)
{
    __uint16_t ii;
    __uint16_t blockDone;
    float compleRate;

    compleRate=barII*100.0/ctx->barN;
    blockDone=(__uint16_t)compleRate*ctx->blockN/100;
    if(barII==ctx->barN)
    {
        printf("\r[100.%%]");
        for(ii=0;ii<ctx->blockN;ii++)
            printf("█");
        printf("\n");
        return;
    }
    printf("\r[%4.1f%%]",compleRate);
    for(ii=0;ii<blockDone;ii++)
        printf("█"); // ■ █ ▅  ▇ █ █ ▮
    for(;ii<ctx->blockN;ii++)
        printf("·");
    
    fflush(stdout);
    return;
}

void pBar_step(pBar_t *ctx, __uint16_t barII)
{
    __uint16_t ii;
    __uint16_t blockDone;
    float compleRate;

    if(barII==ctx->barN)
    {
        printf("\r");
        for(ii=0;ii<ctx->blockN+7;ii++)
            printf(" ");
        printf("\r");
        return;
    }
    compleRate=barII*100.0/ctx->barN;
    blockDone=(__uint16_t)compleRate*ctx->blockN/100;
    printf("\r[%4.1f%%]",compleRate);
    for(ii=0;ii<blockDone;ii++)
        printf("█"); // ■ █ ▅  ▇ █ █ ▮
    for(;ii<ctx->blockN;ii++)
        printf("·");
    fflush(stdout);
    return;
}

void pBar_release(pBar_t *ctx)
{
    free(ctx);
}

void printf_red(const char *s)
{
    printf("\033[0m\033[1;31m%s\033[0m", s);
}

void printf_green(const char *s)
{
    printf("\033[0m\033[1;32m%s\033[0m", s);
}

void printf_yellow(const char *s)
{
    printf("\033[0m\033[1;33m%s\033[0m", s);
}

void printf_blue(const char *s)
{
    printf("\033[0m\033[1;34m%s\033[0m", s);
}

void printf_pink(const char *s)
{
    printf("\033[0m\033[1;35m%s\033[0m", s);
}

void printf_cyan(const char *s)
{
    printf("\033[0m\033[1;36m%s\033[0m", s);
}
